﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Happy.Domain;
using Happy.Activities.Domain.WorkflowInstances;
using Happy.Activities.Domain.Workflows.Internal;

namespace Happy.Activities.Domain.Workflows
{
    /// <summary>
    /// 代表了流程中的一个节点。
    /// </summary>
    public abstract class Activity : Entity<Guid>
    {
        #region 属性

        /// <summary>
        /// 名称
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// 显示名称
        /// </summary>
        public string DisplayName { get; set; }

        /// <summary>
        /// 是否是结束活动。
        /// </summary>
        public bool IsFinal { get; set; }

        /// <summary>
        /// 所在流程标识。
        /// </summary>
        public Guid WorkflowId { get; internal set; }

        #endregion

        /// <summary>
        /// 创建路由分流标记
        /// </summary>
        protected internal virtual string CreateRouterSplitToken(WorkflowContext context, ActivityInstance activityInstance)
        {
            return activityInstance.SplitToken;
        }

        /// <summary>
        /// 创建活动对应的实例。
        /// </summary>
        protected internal virtual ActivityInstance CreateInstance(WorkflowContext context, string routerSplitToken = SplitTokenHelper.DefaultSplitToken)
        {
            return new ActivityInstance
            {
                Id = Guid.NewGuid(),
                ActivityId = this.Id,
                SplitToken = routerSplitToken,
                State = ActivityState.New,
                WorkflowInstanceId = context.WorkflowInstance.Id
            };
        }

        internal void Enter(WorkflowContext context, ActivityInstance activityInstance)
        {
            activityInstance.SetStateToEntering(context);

            if (!this.CanEnter(context, activityInstance))
            {
                return;
            }

            activityInstance.SetStateToEntered(context);

            this.OnEnter(context, activityInstance);
        }

        /// <summary>
        /// 能否进入活动。
        /// </summary>
        protected abstract bool CanEnter(WorkflowContext context, ActivityInstance activityInstance);

        /// <summary>
        /// 进入后执行的逻辑。
        /// </summary>
        protected abstract void OnEnter(WorkflowContext context, ActivityInstance activityInstance);

        internal void Exit(WorkflowContext context, ActivityInstance activityInstance)
        {
            activityInstance.SetStateToExiting(context);

            if (!this.CanExit(context, activityInstance))
            {
                return;
            }

            activityInstance.SetStateToExited(context);

            this.OnExit(context, activityInstance);

            if (this.IsFinal)
            {
                context.WorkflowInstance.SetStateToCompleted(context);
            }
        }

        /// <summary>
        /// 能否进入活动。
        /// </summary>
        protected abstract bool CanExit(WorkflowContext context, ActivityInstance activityInstance);

        /// <summary>
        /// 进入后执行的逻辑。
        /// </summary>
        protected abstract void OnExit(WorkflowContext context, ActivityInstance activityInstance);
    }
}
